/*
 * Copyright (c) 2022 上海市政工程设计研究总院(集团)有限公司 All Rights Reserved.
 */
package com.smedi.ismedi.inmail.core.application.convert;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.smedi.ismedi.constructionproject.api.dto.request.ConstructionProjectUpdateRequest;
import com.smedi.ismedi.file.dto.response.FileInfoResponse;
import com.smedi.ismedi.inmail.core.application.command.*;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.*;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.announcement.Announcement;
import com.smedi.ismedi.inmail.core.domain.aggregatemodel.announcement.Receiver;
import com.smedi.ismedi.inmail.core.domain.dto.AnnouncementQuery;
import com.smedi.ismedi.inmail.core.domain.dto.DownloadFileToZip;
import com.smedi.ismedi.inmail.core.port.adapter.persistence.model.*;
import com.smedi.ismedi.organization.api.dto.request.HrOrgUpdateRequest;
import com.smedi.ismedi.organization.api.dto.response.resp.OrganizationResp;
import com.smedi.ismedi.personnel.api.dto.response.resp.PersonResp;
import org.camunda.bpm.engine.history.HistoricTaskInstance;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.mapstruct.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.smedi.ismedi.inmail.core.infrastructure.constant.ConstantField.ZONE_ID;

/**
 * application Converter
 *
 * @author 15428
 * &#064;date  2022-06-07 15:22:03
 * @since 0.0.1
 */
@Mapper(componentModel = "spring" , unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface AppConverter {
    @Mapping(source = "receiverIds" , target = "receivers" , qualifiedByName = "receiverIdToReceiver" )
    @Mapping(source = "nextDealUserId" , target = "reviewer.id" )
    @Mapping(source = "nextDealUserId" , target = "task.dealPerson.id" )
    @Mapping(source = "comment" , target = "task.comment" )
    @Mapping(source = "attachmentKeys" , target = "attachments" , qualifiedByName = "attachmentKeysToAttachments" )
    Announcement announcementCreateCommandToAnnouncement(AnnouncementCreateCommand announcementCreateCommand);

    AnnouncementQuery announcementRemoveCommandToAnnouncementQuery(AnnouncementRemoveCommand announcementRemoveCommand);

    @Named("attachmentKeysToAttachments" )
    default List<Attachment> attachmentKeysToAttachments(List<String> attachmentKeys) {
        List<Attachment> attachments = new ArrayList<>();
        if (null == attachmentKeys) {
            return attachments;
        }
        for (String attachmentKey : attachmentKeys) {
            attachments.add(new Attachment(attachmentKey));
        }
        return attachments;
    }

    @Mapping(source = "receiverIds" , target = "receivers" , qualifiedByName = "receiverIdToReceiver" )
    @Mapping(source = "nextDealUserId" , target = "reviewer.id" )
    @Mapping(source = "nextDealUserId" , target = "task.dealPerson.id" )
    @Mapping(source = "attachmentKeys" , target = "attachments" , qualifiedByName = "attachmentKeysToAttachments" )
    Announcement updateAnnouncementByAnnouncementEditCommand(@MappingTarget Announcement announcement, AnnouncementEditCommand announcementEditCommand);

    @Mapping(source = "comment" , target = "task.comment" )
    @Mapping(source = "isPublic" , target = "task.isPublic" )
    Announcement updateAnnouncementByAnnouncementReviewCommand(@MappingTarget Announcement announcement, AnnouncementReviewCommand announcementReviewCommand);

    Announcement announcementReadCommandToAnnouncement(AnnouncementReadCommand announcementReadCommand);

    AnnouncementQuery announcementOneQueryToAnnouncementQuery(AnnouncementOneQuery announcementOneQuery);

    AnnouncementQuery announcementListQueryToAnnouncementQuery(AnnouncementListQuery announcementListQuery);

    AnnouncementQuery announcementPageQueryToAnnouncementQuery(AnnouncementPageQuery announcementPageQuery);

    UserActionLogEntity userActionLogToUserActionLogEntity(UserActionLog userActionLog);

    List<ProcessTask> historicTaskInstanceToProcessTask(List<HistoricTaskInstance> historicTaskInstances);

    @Named("dateToLocalDateTime" )
    default LocalDateTime dateToLocalDateTime(Date date) {
        if (null == date) {
            return null;
        }
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.of(ZONE_ID));
    }

    @Named("longToLocalDateTime" )
    default LocalDateTime longToLocalDateTime(Long time) {
        if (null == time) {
            return null;
        }
        return LocalDateTime.ofEpochSecond(time / 1000, 0, ZoneOffset.ofHours(8));
    }

    @Named("longToLocalDate" )
    default LocalDate longToLocalDate(Long time) {
        if (null == time) {
            return null;
        }
        return LocalDateTime.ofEpochSecond(time / 1000, 0, ZoneOffset.ofHours(8)).toLocalDate();
    }

    @Mapping(source = "name" , target = "shortName" )
    @Mapping(source = "dept_id" , target = "dingDeptKey" )
    HrOrgUpdateRequest dingDingDeptToHrOrgUpdateRequest(DingDingDept dingDingDept);

    @Mapping(source = "name" , target = "projectName" )
    @Mapping(source = "dept_id" , target = "dingDeptKey" )
    ConstructionProjectUpdateRequest dingDingDeptToConstructionProjectUpdateRequest(DingDingDept dingDingDept);

    @Mapping(source = "startTime" , target = "startTime" , qualifiedByName = "dateToLocalDateTime" )
    @Mapping(source = "endTime" , target = "endTime" , qualifiedByName = "dateToLocalDateTime" )
    @Mapping(source = "removalTime" , target = "removalTime" , qualifiedByName = "dateToLocalDateTime" )
    @Mapping(target = "owner" , ignore = true)
    @Mapping(target = "assignee" , ignore = true)
    ProcessTask historicTaskInstanceToProcessTask(HistoricTaskInstance historicTaskInstance);

    @Mapping(source = "baseCheckTime" , target = "baseCheckTime" , qualifiedByName = "longToLocalDateTime" )
    @Mapping(source = "workDate" , target = "workDate" , qualifiedByName = "longToLocalDate" )
    @Mapping(source = "userCheckTime" , target = "userCheckTime" , qualifiedByName = "longToLocalDateTime" )
    DingAttendanceResultEntity dingAttendanceResultCommandToDingAttendanceResultEntity(DingAttendanceResultCommand dingAttendanceResultCommand);


    com.smedi.ismedi.inmail.core.domain.aggregatemodel.ProcessInstance processInstanceToProcessInstance(ProcessInstance processInstance);

    AnnouncementQuery announcementReadRecordCommandToAnnouncementQuery(AnnouncementReadRecordCommand announcementReadRecordCommand);

    @Mapping(source = "lastName" , target = "name" )
    List<Person> personRespToPerson(List<PersonResp> personResps);

    @Mapping(source = "lastName" , target = "name" )
    Person personRespToPerson(PersonResp personResp);

    Attachment fileInfoResponseToAttachment(FileInfoResponse fileInfoResponse);

    Organization organizationRespToOrganization(OrganizationResp organizationResp);

    @Named("receiverIdToReceiver" )
    default List<Receiver> receiverIdToReceiver(List<Long> ids) {
        List<Receiver> receivers = new ArrayList<>();
        for (Long id : ids) {
            receivers.add(Receiver.builder().id(id).build());
        }
        return receivers;
    }

    DownloadFileToZip downloadFileToZipCommandToDownloadFileToZip(DownloadFileToZipCommand downloadFileToZipCommand);

    LoginLog loginLogLoginCommandToLoginLog(LoginLogLoginCommand loginLogLoginCommand);

    LoginLog loginLogLogoutCommandToLoginLog(LoginLogLogoutCommand loginLogLogoutCommand);

    @Mapping(source = "loginLogId" , target = "loginLog.id" )
    OperationLog operationLogCreateCommandToOperationLog(OperationLogCreateCommand operationLogCreateCommand);

    Page<LoginLogUserStatics> loginLogUserStaticsEntityToLoginLogUserStatics(Page<LoginLogUserStaticsEntity> loginLogUserStaticsEntities);

    List<LoginLogUserStatics> loginLogUserStaticsEntityToLoginLogUserStatics(List<LoginLogUserStaticsEntity> loginLogUserStaticsEntities);

    Page<LoginLogOrgStatics> loginLogOrgStaticsEntityToLoginLogOrgStatics(Page<LoginLogOrgStaticsEntity> loginLogOrgStaticsEntities);

    List<LoginLogOrgStatics> loginLogOrgStaticsEntityToLoginLogOrgStatics(List<LoginLogOrgStaticsEntity> loginLogOrgStaticsEntities);

    Page<LoginLog> loginLogEntityToLoginLog(Page<LoginLogEntity> loginLogEntityPage);
    LoginLog loginLogEntityToLoginLog(LoginLogEntity loginLogEntity);

    OperationLog operationLogEntityToOperationLog(OperationLogEntity operationLogEntity);

    AppVersion appVersionCreateCommandToAppVersion(AppVersionCreateCommand appVersionCreateCommand);

    AppVersion appVersionUpdateCommandToAppVersion(AppVersionUpdateCommand appVersionCreateCommand);

    AppVersionQuery appVersionRemoveCommandToAppVersionQuery(AppVersionRemoveCommand appVersionRemoveCommand);
}
